package com.tarena.lbs.coupon.controller;

import com.alibaba.excel.EasyExcelFactory;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.zxing.WriterException;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.tarena.lbs.attach.api.AttachApi;
import com.tarena.lbs.attach.pojo.dto.AttachQrDTO;
import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.base.protocol.model.Result;
import com.tarena.lbs.base.protocol.pager.PageResult;
import com.tarena.lbs.common.event.QrCodeDeleteMessage;
import com.tarena.lbs.common.principle.UserPrinciple;
import com.tarena.lbs.common.utils.AuthenticationContextUtils;
import com.tarena.lbs.coupon.api.pojo.param.UserCouponsParam;
import com.tarena.lbs.coupon.config.RabbitChannelManager;
import com.tarena.lbs.coupon.config.RabbitMQConfig;
import com.tarena.lbs.coupon.dao.mapper.UserCouponsMapper;
import com.tarena.lbs.coupon.pojo.param.CouponParam;
import com.tarena.lbs.coupon.pojo.po.CouponPO;
import com.tarena.lbs.coupon.pojo.query.CouponQuery;
import com.tarena.lbs.coupon.pojo.query.UserCouponCodeQuery;
import com.tarena.lbs.coupon.pojo.query.UserCouponQuery;
import com.tarena.lbs.coupon.pojo.vo.CouponVO;
import com.tarena.lbs.coupon.pojo.vo.UserCouponsVO;
import com.tarena.lbs.coupon.service.CouponService;
import com.tarena.lbs.coupon.service.RedisService;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bouncycastle.util.encoders.UTF8;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 处理和优惠券数据业务有关的接口
 */
@RestController
@Slf4j
@Tag(name="优惠券模块")
public class CouponController {
    @Autowired
    private CouponService couponService;
    @Autowired
    private HttpServletRequest request;
    @DubboReference
    private AttachApi attachApi;
    @Autowired
    private UserCouponsMapper userCouponsMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RedisService redisService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    private static final String DELAY_EX="delay_ex";
    private static final String DELAY_Q="delay_q";
    private static final String DLX_EX="dlx_ex";
    private static final String DLX_Q="dlx_q";
    private static final String DLX_RK="dlx_rk";
    @Operation(summary = "查询当前商家优惠券分页列表")
    @PostMapping("/admin/marketing/coupon/info/list")
    public Result<PageResult<CouponVO>> pageList(@RequestBody CouponQuery query) throws BusinessException{
        log.debug("前端传入query:{}",query);
        PageResult<CouponVO>pos=couponService.selectCoupon(query);
        log.debug("pos：{}",pos);
        return new Result<>((pos));
    }


    @Operation(summary = "新增优惠券")
    @PostMapping("/admin/marketing/coupon/info/save")
    public Result<Void> addCoupon(@RequestBody CouponParam couponParam)throws BusinessException{
        log.debug("新增优惠券：{AC}",couponParam);
        couponService.addCoupon(couponParam);
        return Result.success();
    }

    @Operation(summary = "更新优惠券")
    @PostMapping("/admin/marketing/coupon/info/update")
    public Result<Void>updateCoupon(@RequestBody CouponParam couponsParam){
        log.debug("更新优惠券:{}",couponsParam);
        int i=couponService.updateCoupon(couponsParam);
        if (i>0){
            return Result.success();
        }else {
            throw new RuntimeException("更新优惠券失败");
        }
    }
    @Operation(summary = "删除优惠券")
    @PostMapping("/admin/marketing/coupon/info/delete")
    public Result<Void> deleteCoupon(@RequestBody CouponParam couponParam){
        log.debug("删除优惠券:{}",couponParam);
        int i=couponService.deleteCoupon(couponParam.getId());
        if (i>0){
            return Result.success();
        }else {
            throw new RuntimeException("删除优惠券失败");
        }
    }
    @Operation(summary = "查询优惠券详情")
    @GetMapping("/admin/marketing/coupon/info/detail/{id}")
    public Result<CouponVO> detail(@PathVariable("id") Integer id)
        throws BusinessException{
        log.info("查询优惠券详情：{}",id);
        CouponVO couponVO = couponService.detail(id);
        log.info("查询优惠券详情成功：{}",couponVO);
        return new Result<>(couponVO);
    }


    @Operation(summary = "领取优惠券")
    @PostMapping("/marketing/user/receive/save")
    public Result receiveCoupon(@RequestBody UserCouponsParam param)
        throws BusinessException{
        Result result=couponService.userInsertCoupon(param);
        if (result!=Result.success()){
            throw new RuntimeException("没领取到优惠券");
        }
        return Result.success();
    }
    @Operation(summary = "用户领取优惠券列表")
    @PostMapping("/marketing/user/receive/list")
    public Result<PageResult<UserCouponsVO>> receiveList(@RequestBody UserCouponQuery couponQuery)throws BusinessException{
        log.info("控制层用户领取入参:{}",couponQuery);
        PageResult<UserCouponsVO>pos=couponService.selectByCountId(couponQuery);
        log.debug("控制层层返回的pos:{}", pos);
        return new Result<>(pos);
    }
    @Operation(summary = "查看优惠券码的二维码图片")
    @PostMapping("/marketing/user/receive/detail")
    public Result<UserCouponsVO> receiveDetail(@RequestBody UserCouponCodeQuery query)
            throws BusinessException, IOException, WriterException {
        log.debug("query:{}",query);
        String keys=redisService.getValue(query.getCouponCode());
        log.debug("keys:{}",keys);
        UserCouponsVO userCouponsVO = new UserCouponsVO();
        userCouponsVO.setCouponCode(query.getCouponCode());
        if(keys!=null){
            log.debug("url:{}",keys);
            userCouponsVO.setCouponUrl(keys);
            log.debug("redis当中有key");
            log.debug("业务层userCouponsVO:{}",userCouponsVO);
            return new Result<>(userCouponsVO);
            //如果查不到在生成一个
        }else{
            log.debug("redis当中没有key");
            //把二维码url保存到服务器供调用api
            AttachQrDTO attachQrDTO=attachApi.generateQrCode(query.getCouponCode());
            String key= query.getCouponCode();;
            RedisConnection redisConnection=redisTemplate.getConnectionFactory().getConnection();
            RedisSerializer<String>serializer=RedisSerializer.string();
            byte[]keyBytes=serializer.serialize(key);
            String code=attachQrDTO.getUrl();
            String url="http://localhost:5050/files/"+code.substring("E:/files/".length());
            log.debug("url:{}",url);
            userCouponsVO.setCouponUrl(url);
            byte[] valueBytes = serializer.serialize(code);
//            redisConnection.set(keyBytes,valueBytes);
            redisService.setValueWithExpire(
                    query.getCouponCode(),
                    query.getCouponCode(),
                    120,
                    TimeUnit.SECONDS
            );
            log.debug("getCouponCode:{}",query.getCouponCode());
            // 发送延迟消息到RabbitMQ，1小时后删除图片
            sendDelayDeleteMessage( query.getCouponCode(),attachQrDTO.getUrl(), url);
            log.debug("业务层userCouponsVO:{}",userCouponsVO);
            return new Result<>(userCouponsVO);
        }
    }
    @ApiOperation("导入优惠券Excel表格")
    @PostMapping("/admin/marketing/coupon/import")
    public Result<String> importExcle(@RequestPart(value = "file") MultipartFile file) throws IOException {
        log.info("开始导入");
        Integer a = couponService.addCouponExcel(file);
        return new Result<>("成功导入"+ a + "条数据");
    }
    @ApiOperation("导出优惠券Excel表格")
    @GetMapping("/admin/marketing/coupon/out")
    public ResponseEntity<byte[]> importExcel() throws IOException {
        try{
            String fileName = UUID.randomUUID().toString().replace("-", "") + ".xlsx";
            List<CouponVO>data=couponService.getCouponList();

            ByteArrayOutputStream out = new ByteArrayOutputStream();
            EasyExcelFactory.write(out, CouponVO.class)
                    .sheet("优惠券二维码Excel表单")
                    .doWrite(data);
            log.debug("ByteArrayOutputStream:{}",out);
            byte[] excelContent = out.toByteArray();
            // 设置响应头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            // 在导出方法中添加文件名编码处理
            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString());
//                    .replaceAll("\\+", "%20"); // 处理空格编码问题
            headers.setContentDispositionFormData("attachment",encodedFileName);
            log.debug("excelContent:{},headers:{}",excelContent,headers);
            return new ResponseEntity<>(excelContent, headers, HttpStatus.OK);
        }catch (IOException e) {
            log.error("导出失败", e);
            throw e;
        }
    }
private void sendDelayDeleteMessage(String couponCode, String filePath, String imageUrl) {
        try {
            QrCodeDeleteMessage message = new QrCodeDeleteMessage(
                    couponCode,
                    filePath,
                    imageUrl,
                    LocalDateTime.now(),
                    couponCode  // redisKey与couponCode相同
            );
            // 发送到延迟队列
            rabbitTemplate.convertAndSend(
                    RabbitMQConfig.QR_DELAY_EXCHANGE,
                    RabbitMQConfig.QR_DELAY_ROUTING_KEY,
                    message
            );
            log.info("成功发送二维码删除延迟消息，优惠券码：{}，文件路径：{}", couponCode, filePath);
        } catch (Exception e) {
            log.error("发送延迟消息失败，优惠券码：{}", couponCode, e);
            // 发送失败可以记录日志或进行重试，但不影响主流程
        }
    }
}